//
//  SchedulersViewController.swift
//  Example
//
//  Created by T AO on 2022/2/15.
//

import UIKit
import RxSwift

/// （1）调度器（Schedulers）是 RxSwift 实现多线程的核心模块，它主要用于控制任务在哪个线程或队列运行
/// （2）RxSwift 内置了如下几种 Scheduler：
///
///     CurrentThreadScheduler：表示当前线程 Scheduler。（默认使用这个）
///     MainScheduler：表示主线程。如果我们需要执行一些和 UI 相关的任务，就需要切换到该 Scheduler 运行。
///     SerialDispatchQueueScheduler：封装了 GCD 的串行队列。如果我们需要执行一些串行任务，可以切换到这个 Scheduler 运行。
///     ConcurrentDispatchQueueScheduler：封装了 GCD 的并行队列。如果我们需要执行一些并发任务，可以切换到这个 Scheduler 运行。
///     OperationQueueScheduler：封装了 NSOperationQueue。
class SchedulersViewController: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        schedulers()
    }

}

extension SchedulersViewController {
    private func gcd() {
        DispatchQueue.global(qos: .userInitiated).async {
            getPlayList("0")
                .subscribe { json in
                    // 再到主线程显示结果
                    DispatchQueue.main.async {
                        
                    }
                } onFailure: { error in
                    
                }
                .disposed(by: self.disposeBag)
        }
    }
    
    private func schedulers() {
        getPlayList("0")
            .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .userInitiated)) // 后台构建序列
            .observe(on: MainScheduler.instance) // 主线程监听并处理序列结果
            .subscribe { json in
                print("请求成功：\(json)")
            } onFailure: { error in
                print("请求失败：\(error.localizedDescription)")
            }
            .disposed(by: disposeBag)

    }
}

/// 获取豆瓣某频道下的歌曲信息
private func getPlayList(_ channel: String) -> Single<[String: Any]> {
    return Single<[String: Any]>.create { single in
        let url = "https://fm.douban.com/j/mine/playlist?type=n&channel=\(channel)&from=mainsite"
        let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _, error in
            if let error = error {
                single(.failure(error))
                return
            }
            
            guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves), let result = json as? [String: Any] else {
                single(.failure(DataError.cantParseJSON))
                return
            }
            
            single(.success(result))
        }
        
        task.resume()
        
        return Disposables.create { task.cancel() }
    }
}

/**
 subscribeOn 与 observeOn 区别?
 
 1、subscribe(on:)
 
 - 该方法决定数据序列的构建函数在哪个 Scheduler 上运行。
 - 比如上面样例，由于获取数据、解析数据需要花费一段时间的时间，所以通过 subscribeOn 将其切换到后台 Scheduler 来执行。这样可以避免主线程被阻塞。
 
 2、observe(on:)
 
 - 该方法决定在哪个 Scheduler 上监听这个数据序列。
 - 比如上面样例，我们获取并解析完毕数据后又通过 observeOn 方法切换到主线程来监听并且处理结果。
 */
